package com.hjm.project.terminal.record.controller;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.hjm.common.exception.BusinessException;
import com.hjm.common.utils.StringUtils;
import com.hjm.common.utils.security.ShiroUtils;
import com.hjm.common.utils.yh.PoiUtil;
import com.hjm.framework.interceptor.annotation.RepeatSubmit;
import com.hjm.project.ActActive.ActActive.domain.ActActive;
import com.hjm.project.ActActive.ActActive.service.IActActiveService;
import com.hjm.project.ShopOrder.ShopOrder.domain.ShopOrder;
import com.hjm.project.ShopOrder.ShopOrder.service.IShopOrderService;
import com.hjm.project.agentInfo.agentActActive.domain.AgentActActive;
import com.hjm.project.agentInfo.agentActActive.service.IAgentActActiveService;
import com.hjm.project.agentInfo.agentInfo.domain.AgentInfo;
import com.hjm.project.agentInfo.agentInfo.service.IAgentInfoService;
import com.hjm.project.agentInfo.agentPolicy.domain.AgentPolicy;
import com.hjm.project.agentInfo.agentPolicy.service.IAgentPolicyService;
import com.hjm.project.formalPos.branchPos.domain.BranchPos;
import com.hjm.project.formalPos.branchPos.service.IBranchPosService;
import com.hjm.project.job.task.service.IJobTaskService;
import com.hjm.project.retainRewards.domain.RetainRewards;
import com.hjm.project.retainRewards.service.IRetainRewardsService;
import com.hjm.project.terminal.detail.domain.TerminalRecordDetail;
import com.hjm.project.terminal.detail.service.ITerminalRecordDetailService;
import com.hjm.project.terminal.record.domain.PosOperateModel;
import com.hjm.project.terminal.record.domain.TerminalRecord;
import com.hjm.project.terminal.record.domain.TerminalRecordDto;
import com.hjm.project.terminal.record.service.ITerminalRecordService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import com.hjm.framework.aspectj.lang.annotation.Log;
import com.hjm.framework.aspectj.lang.enums.BusinessType;
import com.hjm.framework.web.controller.BaseController;
import com.hjm.framework.web.domain.AjaxResult;
import com.hjm.common.utils.poi.ExcelUtil;
import com.hjm.framework.web.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;

/**
 * 终端划拨记录Controller
 *
 * @author LOVE
 * @date 2020-11-28
 */
@Controller
@RequestMapping("/terminal/record")
public class TerminalRecordController extends BaseController {
    private String prefix = "terminal/record";

    @Resource
    private ITerminalRecordService terminalRecordService;

    @Resource
    private IAgentInfoService agentInfoService;
    @Resource
    private IAgentActActiveService agentActActiveService;
    @Resource
    private IAgentPolicyService agentPolicyService;

    @Resource
    private IShopOrderService shopOrderService;

    @Resource
    private ITerminalRecordDetailService detailService;

    @Resource
    private PlatformTransactionManager txManager;

    @Resource
    private IJobTaskService iJobTaskService;

    @Resource
    private IBranchPosService iBranchPosService;
    @Resource
    private IActActiveService actActiveService;
    @Resource
    private IRetainRewardsService retainRewardsService;

    @RequiresPermissions("terminal:record:view")
    @GetMapping()
    public String record() {
        return prefix + "/record";
    }

    /**
     * 发货划拨记录
     */
    @RequiresPermissions("terminal:record:view")
    @RequestMapping("/fhRecord")
    public String fhRecord(ModelMap map, @RequestParam String orderNo, @RequestParam String agentNum) {
        map.put("orderNo", orderNo);
        map.put("agentNum", agentNum);
        return prefix + "/fhRecord";
    }

    /**
     * 查询终端划拨记录列表
     */
    @RequiresPermissions("terminal:record:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(TerminalRecord terminalRecord) {
        startPage();
        List<TerminalRecord> list = terminalRecordService.selectTerminalRecordList(terminalRecord);
        return getDataTable(list);
    }

    /**
     * 导出终端划拨记录列表
     */
    @RequiresPermissions("terminal:record:export")
    @Log(title = "终端划拨记录", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @ResponseBody
    public AjaxResult export(TerminalRecord terminalRecord) {
        List<TerminalRecord> list = terminalRecordService.selectTerminalRecordList(terminalRecord);
        ExcelUtil<TerminalRecord> util = new ExcelUtil<TerminalRecord>(TerminalRecord.class);
        return util.exportExcel(list, "record");
    }

    /**
     * 新增终端划拨记录
     */
    @GetMapping("/add")
    public String add() {
        return prefix + "/add";
    }

    /**
     * 根据文件计算终端划拨台数
     */
    @PostMapping("/file")
    @ResponseBody
    public AjaxResult file(@RequestParam Map param, TerminalRecord terminalRecord, MultipartFile file, @RequestParam Map maps) throws Exception {
        if (file.getSize() == 0 || file == null) {
            return AjaxResult.warn("请上传正确的终端Excel文件");
        } else {
            File files = null;
            try {
                files = File.createTempFile("prefix", "_" + file.getOriginalFilename());
                file.transferTo(files);
                Map<String, Map<String, Object>> lines = PoiUtil.readExcelContent(files.getPath());
                return AjaxResult.success(lines.size());
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return AjaxResult.warn("请上传正确的终端Excel文件");

        }
    }

    /**
     * 新增保存终端划拨记录
     */
    @RequiresPermissions("terminal:record:add")
    @Log(title = "终端划拨记录", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @ResponseBody
    @RepeatSubmit
    public AjaxResult addSave(TerminalRecord terminalRecord, MultipartFile file, @RequestParam String types, @RequestParam Map map) throws Exception {
        boolean isError = true;
        String message = "";
        List<String> posNos = new ArrayList<>(); //文件
        List<String> posNo = new ArrayList<>(); //SN
        List<String> posNoCj = new ArrayList<>(); //SN

        String actId = terminalRecord.getActId();
        ActActive actActive = actActiveService.selectActActiveById(actId);

        if (Integer.parseInt(terminalRecord.getSim_fee()) <  Integer.parseInt(actActive.getSimFeeReturn())) {
            return AjaxResult.error("流量费收取金额不可小于活动流量费返现金额");
        }

        if (Integer.parseInt(terminalRecord.getService_fee()) < Integer.parseInt(actActive.getServiceFeeReturn())) {
            return AjaxResult.error("服务费收取金额不可小于活动服务费返现金额");
        }


        AgentActActive aaa = new AgentActActive();
        aaa.setAgentNum(terminalRecord.getAgentTarNum());
        aaa.setActId(actId);
        AgentActActive agentActActive = agentActActiveService.selectagentActActiveOne(aaa);
        if (agentActActive == null) {
            return AjaxResult.error("目标代理商未设置政策【" + actActive.getActName() +"】");
        }
        AgentPolicy ap = new AgentPolicy();
        ap.setActId(actId);
        ap.setAgentNum(terminalRecord.getAgentTarNum());
        List<AgentPolicy> agentPolicies = agentPolicyService.selectAgentPolicyList(ap);
        if (CollectionUtils.isEmpty(agentPolicies)) {
            return AjaxResult.error("目标代理商未配置政策【" + actActive.getActName() +"】的结算费率");
        }
        try {
            Map<String, String> resultMap = null;
            //SN
            if (types.equals("1")) {
                //如果是SN号段 默认每次累加1
                String startSn = map.get("startSn").toString();
                if (StringUtils.isEmpty(startSn) || startSn.length() < 16) {
                    return AjaxResult.warn("请输入正确的SN编号:[" + startSn + "]");

                }
                //机具编号前部分
                String startOne = "";
                Integer start = 0;
                if (startSn.length() >= 24) {
                    startOne = startSn.substring(0, 15);
                    start = Integer.parseInt(startSn.substring(15, startSn.length()));
                } else if (startSn.length() >= 20){
                    startOne = startSn.substring(0, 15);
                    start = Integer.parseInt(startSn.substring(15, startSn.length()));
                } else {
                    startOne = startSn.substring(0, 12);
                    start = Integer.parseInt(startSn.substring(12, startSn.length()));
                }
                Integer end = start + terminalRecord.getTotal().intValue();
                for (int i = start; i < end; i++) {
                    String no = terminalRecordService.getPosNoNum(startOne + i);
                    if (no == null) {
                        isError = false;
                        message = "找不到终端号:" + startOne + i;
                        return AjaxResult.warn("找不到终端号:" + startOne + i);
                    }
                    //划拨类型为档位划拨时 效验终端是否是申请人并且是未绑定未激活的(前提是申请人必须存在)
                    if (terminalRecord.getIsSetGrade() == 1 && StringUtils.isNotEmpty(terminalRecord.getApplyAgentNum())) {
                        BranchPos branchPos = new BranchPos();
                        branchPos.setIsbound(Long.parseLong("0"));
                        branchPos.setActivate(Long.parseLong("2"));
                        branchPos.setAgentNum(Long.parseLong(terminalRecord.getApplyAgentNum()));
                        List<BranchPos> branchPos1 = iBranchPosService.selectBranchPosList(branchPos);
                        if (CollectionUtils.isEmpty(branchPos1)) {
                            isError = false;
                            message = "不可划拨非申请人的终端" + startOne + i;
                            return AjaxResult.warn("不可划拨非申请人的终端:" + startOne + i);
                        }
                    }

                    posNo.add(no);
                    posNoCj.add(startOne + i);
                }
                resultMap = terminalRecordService.insertTerminalRecord(terminalRecord, posNo);
            }
            if (types.equals("2")) {
                if (file == null) {
                    isError = false;
                    message = "请上传终端Excel文件";
                    return AjaxResult.warn("请上传终端Excel文件");
                }
                if (file.getSize() == 0) {
                    isError = false;
                    message = "请上传正确的终端Excel文件";
                    return AjaxResult.warn("请上传正确的终端Excel文件");
                }
                File files = File.createTempFile("prefix", "_" + file.getOriginalFilename());
                file.transferTo(files);
                Map<String, Map<String, Object>> lines = PoiUtil.readExcelContent(files.getPath());
                if (lines.size() != Integer.parseInt(terminalRecord.getTotal().toString())) {
                    isError = false;
                    message = "选择机具数量与应划拨机具数量不一致，请检查后重新选择";
                    return AjaxResult.warn("选择机具数量与应划拨机具数量不一致，请检查后重新选择");
                }
                for (Map ss : lines.values()) {
                    String tempPosNo = ss.values().toString().replace("[", "").replace("]", "");
                    String no = terminalRecordService.getPosNoNum(tempPosNo);
                    if (no == null) {
                        isError = false;
                        message = "找不到终端号:" + tempPosNo;
                        return AjaxResult.warn("找不到终端号:" + tempPosNo);
                    }

                    //划拨类型为档位划拨时 效验终端是否是申请人的(前提是申请人必须存在)
                    if (terminalRecord.getIsSetGrade() == 1 && StringUtils.isNotEmpty(terminalRecord.getApplyAgentNum())) {
                        BranchPos branchPos = new BranchPos();
                        branchPos.setAgentNum(Long.parseLong(terminalRecord.getApplyAgentNum()));
                        List<BranchPos> branchPos1 = iBranchPosService.selectBranchPosList(branchPos);
                        if (CollectionUtils.isEmpty(branchPos1)) {
                            isError = false;
                            message = "不可划拨非申请人的终端" + tempPosNo;
                            return AjaxResult.warn("不可划拨非申请人的终端:" + tempPosNo);
                        }
                    }


                    posNos.add(no);
                }

                resultMap = terminalRecordService.insertTerminalRecord(terminalRecord, posNos);
            }
            if ("00".equals(resultMap.get("code"))) {
                //初始化留存信息
                /*RetainRewards ri = new RetainRewards();
                ri.setAgentNum(terminalRecord.getAgentTarNum());
                ri.setActId(actId);
                retainRewardsService.insertRetainRewards(ri);*/
                return AjaxResult.success();
            } else {
                isError = false;
                message = resultMap.get("msg");
                return AjaxResult.warn(resultMap.get("msg"));
            }
        } catch (Exception e) {
            isError = false;
            message = e.getMessage();
            e.printStackTrace();
            throw e;
        } finally {
            hbRecord(isError, message, types, file, posNoCj);
        }
    }

    /**
     * 修改终端划拨记录
     */
    @GetMapping("/edit/{id}")
    public String edit(@PathVariable("id") Long id, ModelMap mmap) {
        TerminalRecord terminalRecord = terminalRecordService.selectTerminalRecordById(id);
        mmap.put("terminalRecord", terminalRecord);
        return prefix + "/edit";
    }

    /**
     * 修改保存终端划拨记录
     */
    @RequiresPermissions("terminal:record:edit")
    @Log(title = "终端划拨记录", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(TerminalRecord terminalRecord) {
        return toAjax(terminalRecordService.updateTerminalRecord(terminalRecord));
    }

    /**
     * 删除终端划拨记录
     */
    @RequiresPermissions("terminal:record:remove")
    @Log(title = "终端划拨记录", businessType = BusinessType.DELETE)
    @PostMapping("/remove")
    @ResponseBody
    public AjaxResult remove(String ids) {
        return toAjax(terminalRecordService.deleteTerminalRecordByIds(ids));
    }

    /**
     * 选择服务商
     */
    @GetMapping("/selectAgentInfo")
    public String selectAgentInfo(ModelMap map) {
        //map.put("belongAgent","100000000");
        return "agentInfo/agentInfo/selectAgentInfo";
    }
    @GetMapping("/selectNextAgentInfo")
    public String selectNextAgentInfo(ModelMap map,String topAgentNum) {
        map.put("topAgentNum",topAgentNum);
        return "agentInfo/agentInfo/selectNextAgentInfo";
    }

    /**
     * 选择服务商
     */
    @GetMapping("/selectAgentInfo2")
    public String selectAgentInfo2(ModelMap map) {
        //map.put("belongAgent","100000000");
        return "agentInfo/agentInfo/selectAgentInfo2";
    }

    /**
     * 终端划拨选择申请人
     *
     * @Param [map]
     * @Return java.lang.String
     */
    @GetMapping("/selectAgentInfoHb")
    public String selectAgentInfoHb(ModelMap map) {
        return "agentInfo/agentInfo/selectAgentInfoHb";
    }

    @GetMapping("/selectAgentInfoAll")
    public String selectAgentInfoAll(ModelMap map) {
        return "agentInfo/agentInfo/selectAgentInfoAll";
    }

    @GetMapping("/selectAgentInfoRecurve")
    public String selectAgentInfoRecurve(String agentNum,ModelMap map) {
        map.put("agentNum",agentNum);
        return "agentInfo/agentInfo/selectAgentInfoRecurve";
    }


    /**
     * 选择服务商
     */
    @GetMapping("/selectActList")
    public String selectActList(ModelMap map) {
        return "ActActive/ActActive/selectActList";
    }

    /**
     * 撤机
     */
    @GetMapping("/revoke")
    public String revoke(ModelMap map) {
        return prefix + "/revoke";
    }

    /**
     * 新增保存终端撤机记录
     */
    @Log(title = "终端撤机记录", businessType = BusinessType.INSERT)
    @PostMapping("/addRevoke")
    @ResponseBody
    public AjaxResult addRevoke(TerminalRecord terminalRecord, MultipartFile file) throws Exception {
        Map<String, String> map = new HashMap<>();
        try {
            List<String> posNo = new ArrayList<>();
            if (file.getSize() == 0 || file == null) {
                return AjaxResult.warn("请上传正确的终端Excel文件");
            } else {
                File files = File.createTempFile("prefix", "_" + file.getOriginalFilename());
                file.transferTo(files);
                Map<String, Map<String, Object>> lines = PoiUtil.readExcelContent(files.getPath());
                if (lines.size() != Integer.parseInt(terminalRecord.getTotal().toString())) {
                    return AjaxResult.warn("选择机具数量与应撤机机具数量不一致，请检查后重新选择");
                }
                for (Map ss : lines.values()) {
                    String tempPosNo = ss.values().toString().replace("[", "").replace("]", "");
                    String no = terminalRecordService.getPosNoNum(tempPosNo);
                    posNo.add(String.valueOf(no));
                }
                map = terminalRecordService.addRevoke(terminalRecord, posNo, file);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
        if ("00".equals(map.get("code"))) {
            return AjaxResult.success();
        } else {
            return AjaxResult.warn(map.get("msg"));
        }
    }


    /**
     * 根据订单和服务商编号 撤机
     */
    @Log(title = "发货终端撤机记录", businessType = BusinessType.INSERT)
    @PostMapping("/fhAddRevoke")
    @ResponseBody
    public AjaxResult fhAddRevoke(TerminalRecord terminalRecord, @RequestParam String orderNo, @RequestParam String agentNum) {
        Map<String, String> map = new HashMap<>();
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus commit = txManager.getTransaction(def);
        try {
            //服务商信息
            AgentInfo agentInfo = agentInfoService.selectAgentInfoByAgentNum(agentNum);
            if (agentInfo == null || agentInfo.getAgentStatus().equals("6")) {
                throw new BusinessException("当前服务商非正常服务商,请先确认服务商状态");
            }
            //订单信息
            ShopOrder shopOrder = shopOrderService.selectShopOrderByIds(orderNo);
            int status = shopOrder.getOrderStatus().intValue();
            if (status != 1 && status != 2) {
                throw new BusinessException("请选择待收货或已完成订单撤机");
            }

            //获取当前订单的机具数量
            Integer goodsNum = shopOrder.getGoodsNum().intValue();
            //根据服务商编号和订单编号获取当前订单划拨过的机具
            TerminalRecord terminalRecord1 = new TerminalRecord();
            terminalRecord1.setAgentTarNum(agentNum);
            terminalRecord1.setOrderNo(orderNo);
            terminalRecord1.setType("5");
            List<TerminalRecord> terminalRecords = terminalRecordService.selectTerminalRecordList(terminalRecord1);
            if (CollectionUtils.isEmpty(terminalRecords)) {
                throw new BusinessException("当前订单未划拨");
            }
            //查看是否撤机
            // 0 未撤机 1 已撤机
            Integer isCj = terminalRecords.get(0).getIsCj();
            if (isCj == 1) {
                throw new BusinessException("当前订单所包含机具已撤机");
            }
            //划拨批次号
            String serial = terminalRecords.get(0).getSerial();
            //根据划拨批次号获取 当前这一批的机具编号
            TerminalRecordDetail recordDetail = new TerminalRecordDetail();
            recordDetail.setSerial(serial);
            List<TerminalRecordDetail> terminalRecordDetails = detailService.selectTerminalRecordDetailList(recordDetail);
            if (CollectionUtils.isEmpty(terminalRecordDetails) || terminalRecordDetails.size() != goodsNum) {
                throw new BusinessException("划拨记录详情数据错误");
            }
            List<String> posNo = new ArrayList<>();
            //组装机具编号
            for (TerminalRecordDetail terminalRecordDetail : terminalRecordDetails) {
                String posNoNum = terminalRecordService.getPosNoNum(terminalRecordDetail.getMachineNum());
                posNo.add(String.valueOf(posNoNum));
            }
            terminalRecord.setOrderNo(orderNo);
            terminalRecord.setAgentTarNum(agentNum);
            terminalRecord.setAgentTarName(agentInfo.getAgentName());
            terminalRecordService.fhAddRevoke(terminalRecord, posNo, orderNo);
            //撤机完成后修改撤机记录
            TerminalRecord terminalRecord2 = new TerminalRecord();
            terminalRecord2.setOrderNo(orderNo);
            terminalRecord2.setAgentTarNum(agentNum);
            terminalRecord2.setIsCj(1);
            terminalRecordService.updateTerminalRecordCj(terminalRecord2);
            //划拨成功后更新订单划拨状态
            ShopOrder shopOrders = new ShopOrder();
            shopOrders.setHbRecord(2);
            shopOrders.setOrderNo(orderNo);
            shopOrderService.updateShopOrder(shopOrders);
        } catch (Exception e) {
            txManager.rollback(commit);
            e.printStackTrace();
            throw e;
        }
        txManager.commit(commit);
        return AjaxResult.success("撤机成功");
    }


    @GetMapping("/exportFile")
    @ResponseBody
    public AjaxResult exportFile() {
        ExcelUtil<PosOperateModel> util = new ExcelUtil<PosOperateModel>(PosOperateModel.class);
        return util.importTemplateExcel("机具划拨模板");
    }


    /**
     * 获取当前代理的指标信息
     *
     * @Param []
     * @Return com.hjm.framework.web.page.TableDataInfo
     */
    @GetMapping("/getAgentIndex")
    @ResponseBody
    public TableDataInfo getAgentIndex(TerminalRecord terminalRecord, MultipartFile file) throws Exception {

        //根据文件内容判断当前代理是否符合指标
        String agentTarNum = terminalRecord.getAgentTarNum();
        //当前代理
        AgentInfo agentInfo = agentInfoService.selectAgentInfoByAgentNum(ShiroUtils.getSysUser().getObjNo());
        //注销状态
        if ("6".equals(agentInfo.getAgentStatus())) {
            throw new BusinessException("当前代理已注销,请联系管理员");
        }
        //目标代理
        AgentInfo targetAgent = agentInfoService.selectAgentInfoByAgentNum(terminalRecord.getAgentTarNum());
        //注销状态
        if ("6".equals(targetAgent.getAgentStatus())) {
            throw new BusinessException("目标代理已注销,确认代理是否正常");
        }

        //查看当前代理是否可以分配指标
        File files = File.createTempFile("prefix", "_" + file.getOriginalFilename());
        file.transferTo(files);
        Map<String, Map<String, Object>> lines = PoiUtil.readExcelContent(files.getPath());
        return null;
    }


    /**
     * @Param [isError 是否成功, message 划拨记录的消息, types 划拨类型, file 文件划拨文件, posNo SN划拨生成的连续SN编号]
     * @Return void
     */
    public void hbRecord(boolean isError, String message, String types, MultipartFile file, List<String> posNo) {
        if (isError) {
            if (types.equals("1")) {
                message = "SN划拨成功";
            }
            if (types.equals("2")) {
                message = "文件划拨成功";
            }
        } else {
            if (types.equals("1")) {
                message += "-[SN划拨失败]";
            }
            if (types.equals("2")) {
                message += "-[文件划拨失败]";
            }
        }
        //如果是文件导入
        if (types.equals("2")) {
            //增加一条导入记录
            iJobTaskService.asyncUploadFile("5", message, ShiroUtils.getSysUser().getLoginName(), file);
        }

        //如果是SN
        if (types.equals("1")) {
            List<TerminalRecordDto> dtoList = new ArrayList<>();
            for (String pNo : posNo) {
                TerminalRecordDto recordDto = new TerminalRecordDto();
                recordDto.setPosNo(pNo);
                dtoList.add(recordDto);
            }
            ExcelUtil<TerminalRecordDto> util = new ExcelUtil<TerminalRecordDto>(TerminalRecordDto.class);
            iJobTaskService.asyncDownLoad("SN划拨导入", Long.parseLong("6"), message, ShiroUtils.getLoginName(), dtoList, util);
        }
    }

    ;


    /**
     * 划拨批次详情
     *
     * @Param [map]
     * @Return java.lang.String
     */
    @GetMapping("/queryDetail")
    public String queryDetail(@RequestParam String serial, ModelMap map) {
        map.put("serial", serial);
        return prefix + "/queryDetail";
    }


}
